$(() => {
  var star = new Star()
  star.init()
})
class Star {
  constructor() {
    this.loadCount = 0
    this.hasRotate = true //是否开始变换
    this.hasLoading = false
    this.hasLoaded = false
    this.container
    this.stats
    this.camera
    this.scene
    this.renderer
    this.particles
    this.geometry
    this.material
    this.glist = [] // glist 点阵数组
    this.around
    this.aroundMaterial
    this.aroundPoints // 环境点组
    this.mouseX = 0,
      this.mouseY = 0
    this.windowHalfX = window.innerWidth / 2
    this.windowHalfY = window.innerHeight / 2
    this.jsonIndex = 0
    this.sceneY = 0
    this.sceneX = 0
    this.Q = 0
    this.effectComposer
    this.hasQRHover = false
    this.mapDot
  }

  init() {
    // renderer 的承载容器
    this.container = document.createElement('div');
    document.body.appendChild(this.container);
    // 初始化相机
    this.camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 100, 50000);
    this.camera.position.set(0, 0, 1e3);
    // 初始化场景
    this.scene = new THREE.Scene();
    this.scene.fog = new THREE.FogExp2(0x000000, 5e-4); // 雾化
    //初始化renderer
    this.renderer = new THREE.WebGLRenderer({
      antialias: false,
      alpha: true
    });
    this.renderer.setClearColor(this.scene.fog, 0)
    //  this.renderer.setClearColor( 0x000000, 1)
    //  this.renderer.setClearColor( 0x111111, 1)
    //  this.renderer.setClearColor( 0x364b7a, .2)
    this.renderer.setPixelRatio(window.devicePixelRatio);
    this.renderer.setSize(window.innerWidth, window.innerHeight);
    this.container.appendChild(this.renderer.domElement);
    // 初始化geometry
    this.geometry = new THREE.Geometry();
    this.around = new THREE.Geometry();
    // 初始化贴图
    var textureLoader = new THREE.TextureLoader();
    this.mapDot = textureLoader.load('img/gradient.png'); // 圆点
    //初始变换点组
    for(let i = 0; i < 20000; i++) {
      var vertex = new THREE.Vector3();
      vertex.x = 4000 * Math.random() - 2000;
      vertex.y = 4000 * Math.random() - 2000;
      vertex.z = 4000 * Math.random() - 2000;
      if(!vertex.tweenvtx) {
        vertex.tweenvtx = new TWEEN.Tween(vertex)
      }
      this.geometry.vertices.push(vertex);
      this.geometry.colors.push(new THREE.Color("rgb(255,255,255)"));
    }
    this.material = new THREE.PointsMaterial({
      size: 5,
      sizeAttenuation: true,
      color: 0xffffff,
      transparent: true,
      opacity: 1,
      map: this.mapDot
    });
    this.material.vertexColors = THREE.VertexColors;
    this.particles = new THREE.Points(this.geometry, this.material);
    window.p = this.particles
    this.scene.add(this.particles);
    //环境点组
    for(let i = 0; i < 1500; i++) {
      var vertex = new THREE.Vector3();
      vertex.x = 2000 * Math.random() - 1000;
      vertex.y = 2000 * Math.random() - 1000;
      vertex.z = 2000 * Math.random() - 1000;
      this.around.vertices.push(vertex);
      this.around.colors.push(new THREE.Color("rgb(255,255,255)"));
    }
    this.aroundMaterial = new THREE.PointsMaterial({
      size: 3,
      sizeAttenuation: true,
      color: 0xffffff,
      transparent: true,
      opacity: 1,
      map: this.mapDot
    });
    this.aroundMaterial.vertexColors = THREE.VertexColors;
    this.aroundPoints = new THREE.Points(this.around, this.aroundMaterial);
    this.scene.add(this.aroundPoints);

    // 加载模型
    this.loadJson();

    //事件监听
    document.addEventListener('mousewheel', this.onDocumentMouseWheel.bind(this), false);
    document.addEventListener('mousemove', this.onDocumentMouseMove.bind(this), false);
    $('.qr-img img').hover(this.qrImgHover.bind(this))
    $('.qr-img img').mouseleave(this.qrImgMouseleave.bind(this))
    this.createEffectComposer();
    this.animate();
    this.runStar();
  }

  qrImgMouseleave() {
    if(!this.hasQRHover || this.leavetimer) {
      return
    }
    this.leavetimer = true
    setTimeout(() => {
      this.leavetimer = false
    }, 2500)
    this.hasQRHover = false
    this.tweenJson(this.jsonIndex)
    this.bannerChange(this.jsonIndex)
  }

  qrImgHover() {
    if(this.hasQRHover || this.overtimer) {
      return
    }
    this.overtimer = true
    setTimeout(() => {
      this.overtimer = false
    }, 2500)
    this.hasQRHover = true
    this.tweenJson(4)
    this.bannerChange(4)
  }

  createEffectComposer() {
    var renderPass = new THREE.RenderPass(this.scene, this.camera);
    //  var bloomPass = new THREE.BloomPass(10, 25, 4, 512);
    var filmPass = new THREE.FilmPass(0, 0, 1500, false);
    var shaderPass = new THREE.ShaderPass(THREE.FocusShader);
    //  var shaderPass = new THREE.ShaderPass(THREE.CopyShader);
    shaderPass.uniforms["screenWidth"].value = window.innerWidth * 2.5;
    shaderPass.uniforms["screenHeight"].value = window.innerHeight * 2.5;
    shaderPass.renderToScreen = true;
    this.effectComposer = new THREE.EffectComposer(this.renderer);
    this.effectComposer.addPass(renderPass);
    //  this.effectComposer.addPass(bloomPass);
    this.effectComposer.addPass(filmPass);
    this.effectComposer.addPass(shaderPass);
  }

  onDocumentMouseMove(event, cope) {
    event.preventDefault();
    //  if(!this.hasRotate && this.hasLoaded) {
    //    this.mouseX = (event.clientX - this.windowHalfX) / 7;
    //    this.mouseY = (event.clientY - this.windowHalfY) / 7;
    //    this.camera.position.x += (-this.mouseX - this.camera.position.x) * 1;
    //    this.camera.position.y += (this.mouseY - this.camera.position.y) * 1;
    //  }
    if(!this.hasRotate && this.hasLoaded) {
      this.sceneY = 3e-4 * (event.clientX - this.windowHalfX);
      this.sceneX = 1e-4 * (event.clientY - this.windowHalfY);
      //    this.geometry.rotateY((event.pageX - this.mouseX) / 1000 * 2 * Math.PI / 100);
      //    this.geometry.rotateX((event.pageY - this.mouseY) / 500 * 2 * Math.PI / 100);
      //    this.mouseX = event.pageX;
      //    this.mouseY = event.pageY;
    }
  }

  onDocumentMouseWheel() {
    if(this.timer || this.hasRotate) {
      return false;
    }
    this.timer = true
    setTimeout(() => {
      this.timer = false
    }, 2500)

    if(this.jsonIndex < 3) {
      this.tweenJson(++this.jsonIndex)
    } else {
      this.tweenJson(this.jsonIndex = 0)
    }
  }

  runStar() {
    var hasLoaded = function(scope) {
      if(scope.loadCount === 5) {
        scope.tweenJson(0)
      } else {
        setTimeout(() => {
          hasLoaded(scope)
        }, 500)
      }
    }
    setTimeout(() => {
      hasLoaded(this)
    }, 1500)
  }

  loadJson() {
    var loader = new THREE.JSONLoader();
    loader.load('json/json1.json', (geo, materials) => {
      geo.center();
      geo.normalize();
      geo.scale(500, 500, 300)
      geo.translate(200, 0, 0)
      this.glist[0] = geo
      this.loadCount++
    })
    loader.load('json/json2.json', (geo, materials) => {
      geo.center();
      geo.normalize();
      geo.rotateX(-Math.PI / 24)
      geo.rotateY(Math.PI - Math.PI / 6)
      geo.scale(600, 600, 300)
      geo.translate(-600, -50, -300)
      this.glist[1] = geo
      this.loadCount++
    })
    loader.load('json/json3.json', (geo, materials) => {
      geo.center();
      geo.normalize();
      geo.rotateY(Math.PI / 2 + Math.PI / 4)
      geo.scale(600, 600, 600)
      geo.translate(400, 0, 0)
      this.glist[2] = geo
      this.loadCount++
    })
    loader.load('json/json4.json', (geo, materials) => {
      geo.center();
      geo.normalize();
      geo.scale(1500, 1500, 1500)
      geo.rotateX(Math.PI * 10 / 180)
      geo.translate(0, -500, 0)
      this.glist[3] = geo
      this.loadCount++
    })
    loader.load('json/qr-1.json', (geo, materials) => {
      geo.center();
      geo.normalize();
      geo.scale(400, 1, 400)
      geo.rotateX(Math.PI / 2)
      //    geo.translate(0, 0, 200)
      this.glist[4] = geo
      this.loadCount++
    })
  }

  tweenJson(index) {
    this.hasLoaded = false;
    setTimeout(() => {
      this.hasLoaded = true;
    }, 2200)
    this.geometry.vertices.forEach((e, i, arr) => {
      var length = this.glist[index].vertices.length;
      var o = this.glist[index].vertices[i % length];
      e.tweenvtx.stop();
      e.tweenvtx.to({
        x: o.x,
        y: o.y,
        z: o.z
      }, 1250).delay(.75 * 1000 * Math.random()).start()
    })
    this.bannerChange(index)
  }

  bannerChange(index) {
    $('.banner.active').removeClass('active')
    $('.banner.json-' + index).addClass('active')
  }

  animate(time) {
    window.requestAnimationFrame(this.animate.bind(this));
    this.render();
  }

  render() {
    if(this.hasRotate) {
      this.geometry.rotateY(Math.PI / 200)
      if(!this.hasLoading) {
        setTimeout(() => {
          this.hasRotate = false
          this.hasLoading = true
          $('.qr-img').addClass('active')
        }, 2000)
      }
    }
    this.around.rotateY(Math.PI / 2000);
    TWEEN.update();
    this.num ? this.num : this.num = 0;
    if(this.hasQRHover) {
      if(this.particles.material.size !== 6) {
        this.particles.rotation.y = 0
        this.particles.material = new THREE.PointsMaterial({
          color: 0xffffff,
          size: 6,
          opacity: 1,
          transparent: true,
          blending: THREE.AdditiveBlending,
          depthTest: false
        })
      }
      this.particles.rotation.y = .2 * Math.sin(this.num += 0.025);
      this.scene.rotation.y = 0;
      this.scene.rotation.x = 0;
    } else {
      if(this.particles.material.size === 6) {
        this.particles.material = new THREE.PointsMaterial({
          size: 5,
          sizeAttenuation: true,
          color: 0xffffff,
          transparent: true,
          opacity: 1,
          blending: THREE.AdditiveBlending,
          depthTest: false,
          map: this.mapDot
        });
      }
      this.particles.rotation.y = .2 * Math.sin(this.num += 0.001);
      this.scene.rotation.y += (this.sceneY - this.scene.rotation.y) / 50;
      this.scene.rotation.x += (this.sceneX - this.scene.rotation.x) / 50;
    }
    if(this.jsonIndex === 3 && this.glist[this.jsonIndex] && !this.hasQRHover) {
      var e = this.glist[this.jsonIndex]
      var t = {
        x: 0,
        y: -150,
        z: 0
      }
      this.geometry.vertices.forEach((i, n) => {
        var r = n % e.vertices.length,
          o = e.vertices[r],
          a = Math.sqrt(Math.pow(i.x - t.x, 2) + Math.pow(i.z - t.z, 2));
        i.y = o.y + Math.sin(a / 70 + this.Q) * a / 30
      });
      this.Q -= .015
    }

    this.camera.lookAt(this.scene.position);
    this.geometry.verticesNeedUpdate = true;
    this.geometry.colorsNeedUpdate = true;

    this.effectComposer.render(this.scene, this.camera);
    //  this.renderer.render(this.scene, this.camera)
  }
}